package com.powerbank.user.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.powerbank.common.entity.PaymentRecord;
import com.powerbank.common.entity.RentalOrder;
import com.powerbank.common.exception.BusinessException;
import com.powerbank.common.result.ResultCode;
import com.powerbank.user.dto.CreatePaymentDTO;
import com.powerbank.user.mapper.PaymentRecordMapper;
import com.powerbank.user.mapper.RentalOrderMapper;
import com.powerbank.user.service.PaymentService;
import com.powerbank.user.service.ThirdPartyPaymentAdapter;
import com.powerbank.user.vo.PaymentResultVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 支付服务实现类
 */
@Slf4j
@Service
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private PaymentRecordMapper paymentRecordMapper;

    @Autowired
    private RentalOrderMapper rentalOrderMapper;

    @Autowired
    @Qualifier("alipayAdapter")
    private ThirdPartyPaymentAdapter alipayAdapter;

    @Autowired
    @Qualifier("wechatAdapter")
    private ThirdPartyPaymentAdapter wechatAdapter;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PaymentResultVO createPayment(Long userId, CreatePaymentDTO paymentDTO) {
        log.info("用户{}创建支付订单 - 订单ID: {}, 支付方式: {}, 金额: {}", 
                userId, paymentDTO.getOrderId(), paymentDTO.getPaymentMethod(), paymentDTO.getPaymentAmount());

        // 1. 验证订单存在且属于当前用户
        RentalOrder order = validateOrderOwnership(userId, paymentDTO.getOrderId());

        // 2. 检查是否已有支付记录
        checkExistingPayment(paymentDTO.getOrderId(), paymentDTO.getPaymentType());

        // 3. 计算实际支付金额（考虑优惠券）
        BigDecimal actualAmount = calculateActualAmount(paymentDTO);

        // 4. 创建支付记录
        PaymentRecord paymentRecord = createPaymentRecord(userId, order, paymentDTO, actualAmount);
        paymentRecordMapper.insert(paymentRecord);

        // 5. 根据支付方式调用第三方支付
        PaymentResultVO result;
        if ("WALLET".equals(paymentDTO.getPaymentMethod())) {
            // 钱包支付
            result = processWalletPayment(paymentRecord);
        } else {
            // 第三方支付
            result = processThirdPartyPayment(paymentRecord, paymentDTO);
        }

        return result;
    }

    @Override
    public PaymentResultVO queryPaymentStatus(String paymentNo) {
        if (StrUtil.isBlank(paymentNo)) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "支付流水号不能为空");
        }

        LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getPaymentNo, paymentNo);
        PaymentRecord paymentRecord = paymentRecordMapper.selectOne(wrapper);

        if (paymentRecord == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "支付记录不存在");
        }

        // 如果是第三方支付且状态为待支付，则查询第三方支付状态
        if (paymentRecord.getPaymentStatus() == 0 && 
            !StrUtil.equals(paymentRecord.getPaymentMethod(), "WALLET")) {
            
            ThirdPartyPaymentAdapter adapter = getPaymentAdapter(paymentRecord.getPaymentMethod());
            Map<String, String> statusInfo = adapter.queryPaymentStatus(paymentRecord.getPlatformOrderId());
            
            // 根据查询结果更新支付状态
            updatePaymentStatusFromThirdParty(paymentRecord, statusInfo);
        }

        return buildPaymentResultVO(paymentRecord);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean handlePaymentCallback(String paymentMethod, String callbackData) {
        log.info("处理{}支付回调", paymentMethod);

        try {
            ThirdPartyPaymentAdapter adapter = getPaymentAdapter(paymentMethod);
            Map<String, String> callbackInfo = adapter.handleCallback(callbackData);

            if (!"true".equals(callbackInfo.get("verified"))) {
                log.warn("支付回调验证失败 - 支付方式: {}", paymentMethod);
                return false;
            }

            // 根据平台订单号查找支付记录
            String platformOrderId = callbackInfo.get("platformOrderId");
            LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(PaymentRecord::getPlatformOrderId, platformOrderId);
            PaymentRecord paymentRecord = paymentRecordMapper.selectOne(wrapper);

            if (paymentRecord == null) {
                log.warn("支付回调处理失败，找不到对应的支付记录 - 平台订单号: {}", platformOrderId);
                return false;
            }

            // 更新支付状态
            updatePaymentStatusFromThirdParty(paymentRecord, callbackInfo);

            log.info("支付回调处理成功 - 支付流水号: {}", paymentRecord.getPaymentNo());
            return true;

        } catch (Exception e) {
            log.error("处理支付回调异常", e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelPayment(Long userId, String paymentNo) {
        LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getPaymentNo, paymentNo)
                .eq(PaymentRecord::getUserId, userId);
        PaymentRecord paymentRecord = paymentRecordMapper.selectOne(wrapper);

        if (paymentRecord == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "支付记录不存在");
        }

        if (paymentRecord.getPaymentStatus() != 0) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "当前状态不允许取消支付");
        }

        // 更新支付状态为已取消
        paymentRecord.setPaymentStatus(3);
        paymentRecord.setUpdatedTime(LocalDateTime.now());
        paymentRecordMapper.updateById(paymentRecord);

        log.info("支付已取消 - 支付流水号: {}", paymentNo);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean applyRefund(Long userId, String paymentNo, BigDecimal refundAmount, String refundReason) {
        LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getPaymentNo, paymentNo)
                .eq(PaymentRecord::getUserId, userId);
        PaymentRecord paymentRecord = paymentRecordMapper.selectOne(wrapper);

        if (paymentRecord == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "支付记录不存在");
        }

        if (paymentRecord.getPaymentStatus() != 1) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "支付状态不正确，无法退款");
        }

        if (refundAmount.compareTo(paymentRecord.getActualAmount()) > 0) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "退款金额不能超过实际支付金额");
        }

        // 调用第三方支付退款
        if (!"WALLET".equals(paymentRecord.getPaymentMethod())) {
            ThirdPartyPaymentAdapter adapter = getPaymentAdapter(paymentRecord.getPaymentMethod());
            Map<String, String> refundResult = adapter.refund(
                    paymentRecord.getPlatformOrderId(),
                    paymentRecord.getPlatformTransactionId(),
                    refundAmount,
                    paymentRecord.getActualAmount(),
                    refundReason
            );

            if (!"SUCCESS".equals(refundResult.get("status"))) {
                throw new BusinessException(ResultCode.PAYMENT_ERROR.getCode(), "退款申请失败");
            }
        }

        // 更新支付记录
        paymentRecord.setRefundAmount(refundAmount);
        paymentRecord.setRefundTime(LocalDateTime.now());
        paymentRecord.setRefundReason(refundReason);
        paymentRecord.setPaymentStatus(4); // 已退款
        paymentRecord.setUpdatedTime(LocalDateTime.now());
        paymentRecordMapper.updateById(paymentRecord);

        log.info("退款申请成功 - 支付流水号: {}, 退款金额: {}", paymentNo, refundAmount);
        return true;
    }

    /**
     * 验证订单所有权
     */
    private RentalOrder validateOrderOwnership(Long userId, Long orderId) {
        RentalOrder order = rentalOrderMapper.selectById(orderId);
        if (order == null) {
            throw new BusinessException(ResultCode.ORDER_NOT_EXIST);
        }

        if (!order.getUserId().equals(userId)) {
            throw new BusinessException(ResultCode.PERMISSION_DENIED);
        }

        return order;
    }

    /**
     * 检查是否已有相同类型的支付记录
     */
    private void checkExistingPayment(Long orderId, String paymentType) {
        LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getOrderId, orderId)
                .eq(PaymentRecord::getPaymentType, paymentType)
                .in(PaymentRecord::getPaymentStatus, 0, 1); // 待支付或已支付

        long count = paymentRecordMapper.selectCount(wrapper);
        if (count > 0) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "已存在相同类型的支付记录");
        }
    }

    /**
     * 计算实际支付金额
     */
    private BigDecimal calculateActualAmount(CreatePaymentDTO paymentDTO) {
        // TODO: 这里可以集成优惠券系统计算优惠金额
        BigDecimal discountAmount = BigDecimal.ZERO;
        if (paymentDTO.getCouponId() != null) {
            // 计算优惠券优惠金额
            discountAmount = BigDecimal.valueOf(0.90); // 模拟优惠0.9元
        }

        BigDecimal actualAmount = paymentDTO.getPaymentAmount().subtract(discountAmount);
        return actualAmount.max(BigDecimal.ZERO);
    }

    /**
     * 创建支付记录
     */
    private PaymentRecord createPaymentRecord(Long userId, RentalOrder order, 
                                              CreatePaymentDTO paymentDTO, BigDecimal actualAmount) {
        PaymentRecord record = new PaymentRecord();
        record.setPaymentNo(generatePaymentNo());
        record.setOrderId(order.getId());
        record.setOrderNo(order.getOrderNo());
        record.setUserId(userId);
        record.setPaymentType(paymentDTO.getPaymentType());
        record.setPaymentMethod(paymentDTO.getPaymentMethod());
        record.setPaymentAmount(paymentDTO.getPaymentAmount());
        record.setActualAmount(actualAmount);
        record.setDiscountAmount(paymentDTO.getPaymentAmount().subtract(actualAmount));
        record.setCouponId(paymentDTO.getCouponId());
        record.setPaymentStatus(0); // 待支付
        record.setExpireTime(LocalDateTime.now().plusMinutes(15)); // 15分钟过期
        record.setRemark(paymentDTO.getRemark());
        record.setCreatedTime(LocalDateTime.now());
        record.setUpdatedTime(LocalDateTime.now());

        return record;
    }

    /**
     * 处理钱包支付
     */
    private PaymentResultVO processWalletPayment(PaymentRecord paymentRecord) {
        // TODO: 实现钱包支付逻辑
        log.info("处理钱包支付 - 支付流水号: {}", paymentRecord.getPaymentNo());
        
        // 模拟钱包支付成功
        paymentRecord.setPaymentStatus(1); // 支付成功
        paymentRecord.setPaymentTime(LocalDateTime.now());
        paymentRecord.setPlatformTransactionId("WALLET_" + System.currentTimeMillis());
        paymentRecordMapper.updateById(paymentRecord);

        return buildPaymentResultVO(paymentRecord);
    }

    /**
     * 处理第三方支付
     */
    private PaymentResultVO processThirdPartyPayment(PaymentRecord paymentRecord, CreatePaymentDTO paymentDTO) {
        ThirdPartyPaymentAdapter adapter = getPaymentAdapter(paymentDTO.getPaymentMethod());
        
        String subject = "充电宝" + paymentDTO.getPaymentType();
        String description = String.format("订单号: %s, 金额: %s", 
                paymentRecord.getOrderNo(), paymentRecord.getActualAmount());
        String notifyUrl = "https://api.powerbank.com/payment/callback/" + paymentDTO.getPaymentMethod().toLowerCase();
        String returnUrl = "https://app.powerbank.com/payment/return";

        Map<String, String> paymentInfo = adapter.createPayment(
                paymentRecord.getPaymentNo(),
                paymentRecord.getActualAmount(),
                subject,
                description,
                paymentDTO.getClientIp(),
                notifyUrl,
                returnUrl
        );

        // 更新支付记录
        paymentRecord.setPlatformOrderId(paymentInfo.get("platformOrderId"));
        paymentRecordMapper.updateById(paymentRecord);

        // 构建返回结果
        PaymentResultVO result = buildPaymentResultVO(paymentRecord);
        result.setPaymentUrl(paymentInfo.get("paymentUrl"));
        result.setQrCodeData(paymentInfo.get("qrCodeData"));

        return result;
    }

    /**
     * 根据支付方式获取适配器
     */
    private ThirdPartyPaymentAdapter getPaymentAdapter(String paymentMethod) {
        switch (paymentMethod) {
            case "ALIPAY":
                return alipayAdapter;
            case "WECHAT":
                return wechatAdapter;
            default:
                throw new BusinessException(ResultCode.PAYMENT_METHOD_NOT_SUPPORTED);
        }
    }

    /**
     * 根据第三方支付结果更新支付状态
     */
    private void updatePaymentStatusFromThirdParty(PaymentRecord paymentRecord, Map<String, String> statusInfo) {
        String status = statusInfo.get("status");
        
        if ("SUCCESS".equals(status)) {
            paymentRecord.setPaymentStatus(1); // 支付成功
            paymentRecord.setPaymentTime(LocalDateTime.now());
            paymentRecord.setPlatformTransactionId(statusInfo.get("platformTransactionId"));
        } else if ("FAILED".equals(status)) {
            paymentRecord.setPaymentStatus(2); // 支付失败
        }
        // WAITING状态不更新

        paymentRecord.setUpdatedTime(LocalDateTime.now());
        paymentRecordMapper.updateById(paymentRecord);
    }

    /**
     * 构建支付结果VO
     */
    private PaymentResultVO buildPaymentResultVO(PaymentRecord paymentRecord) {
        PaymentResultVO vo = new PaymentResultVO();
        BeanUtils.copyProperties(paymentRecord, vo);
        vo.setPaymentId(paymentRecord.getId());
        vo.setPaymentStatusDesc(getPaymentStatusDesc(paymentRecord.getPaymentStatus()));

        return vo;
    }

    /**
     * 获取支付状态描述
     */
    private String getPaymentStatusDesc(Integer paymentStatus) {
        switch (paymentStatus) {
            case 0:
                return "待支付";
            case 1:
                return "支付成功";
            case 2:
                return "支付失败";
            case 3:
                return "已取消";
            case 4:
                return "已退款";
            default:
                return "未知状态";
        }
    }

    /**
     * 生成支付流水号
     */
    private String generatePaymentNo() {
        return "PAY" + System.currentTimeMillis() + RandomUtil.randomLong(1000, 9999);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean processRefund(Long userId, String paymentNo, BigDecimal refundAmount, String refundReason) {
        log.info("处理退款请求 - 支付流水号: {}, 退款金额: {}, 退款原因: {}", paymentNo, refundAmount, refundReason);

        LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getPaymentNo, paymentNo)
                .eq(PaymentRecord::getUserId, userId);
        PaymentRecord paymentRecord = paymentRecordMapper.selectOne(wrapper);

        if (paymentRecord == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "支付记录不存在");
        }

        if (paymentRecord.getPaymentStatus() != 1) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "支付状态不正确，无法退款");
        }

        if (refundAmount.compareTo(paymentRecord.getActualAmount()) > 0) {
            throw new BusinessException(ResultCode.PARAM_ERROR.getCode(), "退款金额不能超过实际支付金额");
        }

        // 调用第三方支付退款
        if (!"WALLET".equals(paymentRecord.getPaymentMethod())) {
            ThirdPartyPaymentAdapter adapter = getPaymentAdapter(paymentRecord.getPaymentMethod());
            Map<String, String> refundResult = adapter.refund(
                    paymentRecord.getPlatformOrderId(),
                    paymentRecord.getPlatformTransactionId(),
                    refundAmount,
                    paymentRecord.getActualAmount(),
                    refundReason
            );

            if (!"SUCCESS".equals(refundResult.get("status"))) {
                throw new BusinessException(ResultCode.PAYMENT_REFUND_FAILED.getCode(), "退款失败: " + refundResult.get("message"));
            }
        }

        // 更新支付记录状态
        paymentRecord.setPaymentStatus(2); // 已退款
        paymentRecord.setRefundAmount(refundAmount);
        paymentRecord.setRefundReason(refundReason);
        paymentRecord.setRefundTime(LocalDateTime.now());
        paymentRecord.setUpdatedTime(LocalDateTime.now());
        paymentRecordMapper.updateById(paymentRecord);

        log.info("退款处理成功 - 支付流水号: {}", paymentNo);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean processRechargeCallback(String paymentNo) {
        log.info("处理充值回调 - 支付流水号: {}", paymentNo);

        // 1. 查找支付记录
        LambdaQueryWrapper<PaymentRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PaymentRecord::getPaymentNo, paymentNo);
        PaymentRecord paymentRecord = paymentRecordMapper.selectOne(wrapper);

        if (paymentRecord == null) {
            log.warn("充值回调处理失败，找不到对应的支付记录 - 支付流水号: {}", paymentNo);
            return false;
        }

        // 2. 检查支付状态
        if (paymentRecord.getPaymentStatus() != 0) {
            log.info("充值回调已处理过 - 支付流水号: {}, 当前状态: {}", paymentNo, paymentRecord.getPaymentStatus());
            return true;
        }

        // 3. 更新支付状态为已支付
        paymentRecord.setPaymentStatus(1); // 已支付
        paymentRecord.setUpdatedTime(LocalDateTime.now());
        paymentRecordMapper.updateById(paymentRecord);

        // 4. 更新用户钱包余额（这里简化处理，实际应该调用钱包服务）
        // TODO: 调用钱包服务增加余额
        log.info("用户{}充值成功，金额: {}", paymentRecord.getUserId(), paymentRecord.getActualAmount());

        log.info("充值回调处理成功 - 支付流水号: {}", paymentNo);
        return true;
    }
}